/*
 * Class responsable for all the rules of the game
 * 
 */

package dominosaude.dominoesControler;

import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Random;

/**
 *
 * @author pedromedeiros
 */
public class DominoesControl {

    private Jogador jogador1 = new Jogador();
    private Jogador jogador2 = new Jogador();
    private dominosaude.dominoesView.MesaDominous mesa;
    private HostJogo RemoteHost = null;
    private ClientJogo RemoteClient = null;

    /**
     * @return the PlayOnStatus
     */
    public PlayOnlineStatus getPlayOnStatus() {
        return PlayOnStatus;
    }

    /**
     * @param PlayOnStatus the PlayOnStatus to set
     */
    public void setPlayOnStatus(PlayOnlineStatus PlayOnStatus) {
        System.out.println("Set play On Status");
        this.PlayOnStatus = PlayOnStatus;
    }

    public enum Status {JOGADOR1_VEZ, JOGADOR2_VEZ, JOGADOR1_GANHA, JOGADOR2_GANHA, UNKOWN};
    private Status StatusJogo = Status.UNKOWN;

    public enum PlayOnlineStatus { NOT_CONNECT, HOST_WAITING, HOST_CONNECTED, CLIENT_WAITING, CLIENT_CONNECTED }
    private PlayOnlineStatus PlayOnStatus = PlayOnlineStatus.NOT_CONNECT;

    private ArrayList maoJogador1 = new ArrayList();
    private ArrayList maoJogador2 = new ArrayList();
    private ArrayList pecasMesa = new ArrayList();


    public void novoJogo1Jogador(){

        jogador1.setHumano(true);
        jogador2.setHumano(false);

        setGameStatus(Status.JOGADOR1_VEZ);

        criaEDistribuiPecas();

    }

    public void novoJogo2Jogadores(dominosaude.dominoesView.MesaDominous m){

        mesa = m;
        jogador1.setHumano(true);
        jogador2.setHumano(true);

        RemoteHost = new HostJogo(this);
        System.out.println("Set play On Status 1");
        setPlayOnStatus(PlayOnlineStatus.HOST_WAITING);

        //criaEDistribuiPecas();

    }

    public void conectaJogo2jogadores(dominosaude.dominoesView.MesaDominous m) throws RemoteException, AlreadyBoundException{
        mesa = m;
        jogador1.setHumano(true);
        jogador2.setHumano(true);
        RemoteClient = new ClientJogo(this);
        RemoteClient.stub.ClientConnected();
//        setPlayOnStatus(PlayOnStatus.CLIENT_WAITING);
    }

    public String getTextoAviso()
    {
        String s;
        
        switch(getGameStatus())
        {
            case JOGADOR1_VEZ:
                s = "Vez do Jogador 1";
                break;

            case JOGADOR2_VEZ:
                s = "Vez do Jogador 2";
                break;

            case UNKOWN:
                s = null;
                break;


            default:
                s = null;

        }
        return s;
    }

    /*
     * @return TRUE - jogada realizada | FALSE - jogada pendente
     *  
     */
    public boolean realizaJogadaJ1(Tile t)
    {
        if (pecasMesa.size() == 0)
        {
            pecasMesa.add(t);
            maoJogador1.remove(t);
            return true;
        }else{
            int ponta1, ponta2, auxSize;
            
            Tile tAux1, tAux2;
            
            if (pecasMesa.size() == 1)
            {
                ponta1 = ((Tile) pecasMesa.get(0) ).getLado1();
                ponta2 = ((Tile) pecasMesa.get(0) ).getLado2();
            }else
            {
                tAux1 = (Tile) pecasMesa.get(0);
                tAux2 = (Tile) pecasMesa.get(1);
                if (tAux1.getLado1() == tAux2.getLado1() || tAux1.getLado1() == tAux2.getLado2() )
                {
                    ponta1 = tAux1.getLado2();
                }else
                {
                    ponta1 = tAux1.getLado1();
                }

                tAux1 = (Tile) pecasMesa.get(pecasMesa.size() - 1);
                tAux2 = (Tile) pecasMesa.get(pecasMesa.size() - 2);

                if (tAux1.getLado1() == tAux2.getLado1() || tAux1.getLado1() == tAux2.getLado2() )
                {
                    ponta2 = tAux1.getLado2();
                }else
                {
                    ponta2 = tAux1.getLado1();
                }

                System.out.println("ponta 1 =="+ponta1 + " ponta2 == "+ponta2);


            }

            if(ponta1 == t.getLado1() || ponta1 == t.getLado2())
            {
                pecasMesa.add(0, t);
                System.out.println("t.lados "+ t.getLado1() +" "+t.getLado2());
                System.out.println(" index "+pecasMesa.indexOf(t));
                maoJogador1.remove(pecasMesa.indexOf(t));
                return true;
            }else if(ponta2 == t.getLado1() || ponta2 == t.getLado2())
            {
                pecasMesa.add(t);
                System.out.println("t.lados "+ t.getLado1() +" "+t.getLado2());
                System.out.println(" index "+pecasMesa.indexOf(t));
                maoJogador1.remove(pecasMesa.indexOf(t));
                return true;
            }else
            {
                return false;
            }

        }
        


    }

    /*
     * @return TRUE - jogada realizada | FALSE - jogada pendente
     *
     */
    public boolean realizaJogadaJ1Index (int index)
    {
        Tile t = (Tile) maoJogador1.get(index);

        if (getGameStatus() != Status.JOGADOR1_VEZ)
        {
            return false;
        }

        if (pecasMesa.size() == 0)
        {
            pecasMesa.add(maoJogador1.get(index));
            maoJogador1.remove(index);
            setGameStatus(Status.JOGADOR2_VEZ);
            return true;
        }else{
            int ponta1, ponta2, auxSize;

            Tile tAux1, tAux2;

            if (pecasMesa.size() == 1)
            {
                ponta1 = ((Tile) pecasMesa.get(0) ).getLado1();
                ponta2 = ((Tile) pecasMesa.get(0) ).getLado2();
            }else
            {

                
                tAux1 = (Tile) pecasMesa.get(0);
                tAux2 = (Tile) pecasMesa.get(1);
                if (tAux1.getLado1() == tAux2.getLado1() || tAux1.getLado1() == tAux2.getLado2() )
                {
                    ponta1 = tAux1.getLado2();
                }else
                {
                    ponta1 = tAux1.getLado1();
                }

                tAux1 = (Tile) pecasMesa.get(pecasMesa.size() - 1);
                tAux2 = (Tile) pecasMesa.get(pecasMesa.size() - 2);

                if (tAux1.getLado1() == tAux2.getLado1() || tAux1.getLado1() == tAux2.getLado2() )
                {
                    ponta2 = tAux1.getLado2();
                }else
                {
                    ponta2 = tAux1.getLado1();
                }

                System.out.println("ponta 1 =="+ponta1 + " ponta2 == "+ponta2);

            }

            if(ponta1 == t.getLado1() || ponta1 == t.getLado2())
            {
                boolean possivel = false;
                int aux;
                Tile tileAux;
                pecasMesa.add(0, t);
                System.out.println("t.lados "+ t.getLado1() +" "+t.getLado2());
                System.out.println(" index "+index);
                maoJogador1.remove(index);
                
                // verificar se é possivel uma jogada com a peca do jogador 2
                
                aux = getMaoJogador2().size();
                for (int i = 0; i < aux; i++)
                {
                    tileAux = (Tile) getMaoJogador2().get(i);
                    if ((tileAux.getLado1() == ponta1) ||
                        (tileAux.getLado1() == ponta2) ||
                        (tileAux.getLado2() == ponta1) ||
                        (tileAux.getLado2() == ponta2) )
                    {
                        possivel = true;
                    }
                }
                if (possivel == true)
                {
                    setGameStatus(Status.JOGADOR2_VEZ);
                }else
                {
                    aux = getMaoJogador1().size();
                    for (int i = 0; i < aux; i++)
                    {
                        tileAux = (Tile) getMaoJogador1().get(i);
                        if ((tileAux.getLado1() == ponta1) ||
                            (tileAux.getLado1() == ponta2) ||
                            (tileAux.getLado2() == ponta1) ||
                            (tileAux.getLado2() == ponta2) )
                        {
                            possivel = true;
                        }
                    }
                    if(possivel == true)
                    {
                        setGameStatus(Status.JOGADOR1_VEZ);
                    }
                    else
                    {
                        setGameStatus(Status.UNKOWN);
                    }
                }
                return true;
            }else if(ponta2 == t.getLado1() || ponta2 == t.getLado2())
            {
                int aux;
                Tile tileAux;
                boolean possivel = false;
                pecasMesa.add(t);
                System.out.println("t.lados "+ t.getLado1() +" "+t.getLado2());
                System.out.println(" index "+index);
                maoJogador1.remove(index);

                //  verificar se é possivel uma jogada com a peca do jogador 2
                 
                aux = getMaoJogador2().size();
                for (int i = 0; i < aux; i++)
                {
                    tileAux = (Tile) getMaoJogador2().get(i);
                    if ((tileAux.getLado1() == ponta1) ||
                        (tileAux.getLado1() == ponta2) ||
                        (tileAux.getLado2() == ponta1) ||
                        (tileAux.getLado2() == ponta2) )
                    {
                        possivel = true;
                    }
                }
                if (possivel == true)
                {
                    setGameStatus(Status.JOGADOR2_VEZ);
                }else
                {
                    aux = getMaoJogador1().size();
                    for (int i = 0; i < aux; i++)
                    {
                        tileAux = (Tile) getMaoJogador1().get(i);
                        if ((tileAux.getLado1() == ponta1) ||
                            (tileAux.getLado1() == ponta2) ||
                            (tileAux.getLado2() == ponta1) ||
                            (tileAux.getLado2() == ponta2) )
                        {
                            possivel = true;
                        }
                    }
                    if(possivel == true)
                    {
                        setGameStatus(Status.JOGADOR1_VEZ);
                    }
                    else
                    {
                        setGameStatus(Status.UNKOWN);
                    }
                }
                
                return true;
            }else
            {
                setGameStatus(Status.JOGADOR1_VEZ);
                return false;
            }
        }

    }


    /*
     * @return TRUE - jogada realizada | FALSE - jogada pendente
     *
     */
    public boolean realizaJogadaJ2Index (int index)
    {
        Tile t = (Tile) maoJogador2.get(index);
        if (getGameStatus() != Status.JOGADOR2_VEZ)
        {
            return false;
        }

        if (pecasMesa.size() == 0)
        {

            pecasMesa.add(maoJogador2.get(index));
            maoJogador2.remove(index);
            setGameStatus(Status.JOGADOR1_VEZ);
            return true;
        }else{
            int ponta1, ponta2, auxSize;

            Tile tAux1, tAux2;

            if (pecasMesa.size() == 1)
            {
                ponta1 = ((Tile) pecasMesa.get(0) ).getLado1();
                ponta2 = ((Tile) pecasMesa.get(0) ).getLado2();
            }else
            {
                tAux1 = (Tile) pecasMesa.get(0);
                tAux2 = (Tile) pecasMesa.get(1);
                if (tAux1.getLado1() == tAux2.getLado1() || tAux1.getLado1() == tAux2.getLado2() )
                {
                    ponta1 = tAux1.getLado2();
                }else
                {
                    ponta1 = tAux1.getLado1();
                }

                tAux1 = (Tile) pecasMesa.get(pecasMesa.size() - 1);
                tAux2 = (Tile) pecasMesa.get(pecasMesa.size() - 2);

                if (tAux1.getLado1() == tAux2.getLado1() || tAux1.getLado1() == tAux2.getLado2() )
                {
                    ponta2 = tAux1.getLado2();
                }else
                {
                    ponta2 = tAux1.getLado1();
                }

                System.out.println("ponta 1 =="+ponta1 + " ponta2 == "+ponta2);
            }

            if(ponta1 == t.getLado1() || ponta1 == t.getLado2())
            {
                int aux;
                Tile tileAux;
                boolean possivel = false;
                pecasMesa.add(0, t);
                System.out.println("t.lados "+ t.getLado1() +" "+t.getLado2());
                System.out.println(" index "+index);
                maoJogador2.remove(index);

                System.out.println("debug 1");
                // verifica se é possivel uma jogada do jogador 1
                aux = getMaoJogador1().size();
                for (int i = 0; i < aux; i++)
                {
                    tileAux = (Tile) getMaoJogador1().get(i);
                    if ((tileAux.getLado1() == ponta1) ||
                        (tileAux.getLado1() == ponta2) ||
                        (tileAux.getLado2() == ponta1) ||
                        (tileAux.getLado2() == ponta2) )
                    {
                        possivel = true;
                    }
                }

                if (possivel == true)
                {
                    setGameStatus(Status.JOGADOR1_VEZ);
                }else
                {
                    aux = getMaoJogador2().size();
                    for (int i = 0; i < aux; i++)
                    {
                        tileAux = (Tile) getMaoJogador2().get(i);
                        if ((tileAux.getLado1() == ponta1) ||
                            (tileAux.getLado1() == ponta2) ||
                            (tileAux.getLado2() == ponta1) ||
                            (tileAux.getLado2() == ponta2) )
                        {
                            possivel = true;
                        }
                    }
                    if(possivel == true)
                    {
                        setGameStatus(Status.JOGADOR2_VEZ);
                    }
                    else
                    {
                        setGameStatus(Status.UNKOWN);
                    }
                }

                return true;
            }else if(ponta2 == t.getLado1() || ponta2 == t.getLado2())
            {
                int aux;
                Tile tileAux;
                boolean possivel = false;
                pecasMesa.add(t);
                System.out.println("t.lados "+ t.getLado1() +" "+t.getLado2());
                System.out.println(" index "+index);
                maoJogador2.remove(index);
                System.out.println("debug 2");
                // verifica se é possivel uma jogada do jogador 1
                aux = getMaoJogador1().size();
                for (int i = 0; i < aux; i++)
                {
                    tileAux = (Tile) getMaoJogador1().get(i);
                    if ((tileAux.getLado1() == ponta1) ||
                        (tileAux.getLado1() == ponta2) ||
                        (tileAux.getLado2() == ponta1) ||
                        (tileAux.getLado2() == ponta2) )
                    {
                        possivel = true;
                    }
                }

                if (possivel == true)
                {
                    setGameStatus(Status.JOGADOR1_VEZ);
                }else
                {
                    aux = getMaoJogador2().size();
                    for (int i = 0; i < aux; i++)
                    {
                        tileAux = (Tile) getMaoJogador2().get(i);
                        if ((tileAux.getLado1() == ponta1) ||
                            (tileAux.getLado1() == ponta2) ||
                            (tileAux.getLado2() == ponta1) ||
                            (tileAux.getLado2() == ponta2) )
                        {
                            possivel = true;
                        }
                    }
                    if(possivel == true)
                    {
                        setGameStatus(Status.JOGADOR2_VEZ);
                    }
                    else
                    {
                        setGameStatus(Status.UNKOWN);
                    }
                }

                return true;
            }else
            {
                setGameStatus(Status.JOGADOR2_VEZ);
                return false;
            }

        }

    }

    /*
     * volta controle pra mesa, distribui pecas
     *
     */
    public void criarJogo2Jogadores() throws RemoteException{
        System.out.println("executando no host!");
        criaEDistribuiPecas();
        System.out.println("Set play On Status 3");
        setPlayOnStatus(PlayOnStatus.HOST_CONNECTED);
        mesa.MPdesenhaPecas();
        setGameStatus(Status.JOGADOR1_VEZ);
        RemoteHost.stubClient.jogar(getMaoJogador1(), getMaoJogador2(), getPecasMesa(),0);
    }

    public void MPRecriaEDistribuiPecasClient(ArrayList maoJ1, ArrayList maoJ2, ArrayList Pmesa)
    {
        maoJogador1 = maoJ1;
        maoJogador2 = maoJ2;
        pecasMesa = Pmesa;
        System.out.println("Set play On Status 3");
        setPlayOnStatus(PlayOnStatus.CLIENT_CONNECTED);
        setGameStatus(Status.JOGADOR1_VEZ);
        mesa.MPdesenhaPecas();
    }

    public void MPRealizaJogadaRemota(ArrayList maoJ1, ArrayList maoJ2,ArrayList Pmesa)
    {
        maoJogador1 = maoJ1;
        maoJogador2 = maoJ2;
        pecasMesa = Pmesa;
        mesa.MPdesenhaPecas();
    }

    private void criaEDistribuiPecas(){
        
        ArrayList listaDeCriacao = new ArrayList();
        int aux = 0;
        for (int i = 6; i >= 0 ;i--)
        {
            for (int j = i; j >= 0 ;j--)
            {
                Tile tile = new Tile(i,j);
                listaDeCriacao.add(tile);
                aux++;
            }

        }

        while(listaDeCriacao.size() > 0)
        {
            Random r = new Random();

            int indice =  r.nextInt(listaDeCriacao.size());

            getMaoJogador1().add(listaDeCriacao.get(indice));
            listaDeCriacao.remove(indice);

            indice =  r.nextInt(listaDeCriacao.size());

            getMaoJogador2().add(listaDeCriacao.get(indice));
            listaDeCriacao.remove(indice);
        }

        // desaloca lista de criacao
        listaDeCriacao = null;

        System.out.println( "mao1 == "+getMaoJogador1().size() );
        System.out.println( "mao2 == "+getMaoJogador2().size() );
    }



    public ArrayList embaralha(){
        return null;
    }

    public ArrayList entregaPecas(int ArrayList[]){
        //Recebe um array de pecas, seriam 7 pecas para cada jogador em jogo
        return null;
    }

    public ArrayList separarPecas(int numJogadores){
        //Recebe o numero de jogadores no jogo para separar as pecas em quantidade corretas
        //caso não seja utilizada todas as peças, as que sobraram devem ser disponibilizadas para compra
        return null;
    }

    public int possibilidadeDejogada(int ArrayList[]){
        int jogada = 0;
        //verifica a possibilidade de jogada do jogador, se ele pode ou não jogar aquela peça
        //deve receber as duas pontas da mesa,para que assim ele indique qual peça o jogador pode jogar ou se ele deve passar ou comprar
        //recebe um array com as 2 pontas da mesa
        return jogada;
    }

    public int jogada(int pontaDaJogada, int peca){
        int jogada = 0;
        //Metodo que fara a jogada do jogador, recebera as pontas disponiveis e a peca para jogada
        return jogada;
    } 

    public void exibirPecas (int ArrayList[]){
        //metodo que mostrara as pecas para o jogador, recebe as pecas selecionadas apos o embaralhamento
    }


    public Status getGameStatus()
    {
        return StatusJogo;
    }

    public void setGameStatus(Status s)
    {
        StatusJogo = s;
    }


    /**
     * @return the maoJogador1
     */
    public ArrayList getMaoJogador1() {
        return maoJogador1;
    }

    /**
     * @param maoJogador1 the maoJogador1 to set
     */
    public void setMaoJogador1(ArrayList maoJogador1) {
        this.maoJogador1 = maoJogador1;
    }

    /**
     * @return the maoJogador2
     */
    public ArrayList getMaoJogador2() {
        return maoJogador2;
    }

    /**
     * @param maoJogador2 the maoJogador2 to set
     */
    public void setMaoJogador2(ArrayList maoJogador2) {
        this.maoJogador2 = maoJogador2;
    }

    /**
     * @return the pecasMesa
     */
    public ArrayList getPecasMesa() {
        return pecasMesa;
    }

    /**
     * @param pecasMesa the pecasMesa to set
     */
    public void setPecasMesa(ArrayList pecasMesa) {
        this.pecasMesa = pecasMesa;
    }

    public boolean hideTileJ1()
    {
        if (getPlayOnStatus() == PlayOnlineStatus.CLIENT_CONNECTED)
        {
            System.out.println("hide Tile J1 true");
            return true;
        }
        else
        {
            System.out.println("hide Tile J1 false");
            return false;
        }

    }

    public boolean hideTileJ2()
    {
        if (getPlayOnStatus() == PlayOnlineStatus.HOST_CONNECTED)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public boolean MPisRunningAGame()
    {
        if (getGameStatus() == Status.UNKOWN)
        {
            return false;
        }
        else
        {
            return true;
        }
    }

    public boolean MPisRunningMultplayer()
    {
        if (getPlayOnStatus() == PlayOnStatus.NOT_CONNECT)
        {
            return false;
        }
        else
        {
            return true;
        }
    }

    public void MPProcessRemoteJogar() throws RemoteException
    {
        if (getPlayOnStatus() == PlayOnStatus.CLIENT_CONNECTED)
        {
            RemoteClient.stub.jogar(maoJogador1, maoJogador2, pecasMesa,0);
        }
        else
        {
            RemoteHost.stubClient.jogar(maoJogador1, maoJogador2, pecasMesa,0);
        }
    }



}
